#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>

struct Cmd {
  int argc;
  char *argv[16];
} cmd;

void init_cmd(){  //初始化
  cmd.argc = 0;
  for(int i=0;i<16;i++){cmd.argv[i] = NULL;}
}

void cut_str(char *command){
  init_cmd();
  char *str = (char*)malloc(sizeof(command));
  strcpy(str,command);
  cmd.argv[cmd.argc] = strtok(str," \n");
  while(cmd.argv[cmd.argc] != NULL){
    cmd.argc++;
    cmd.argv[cmd.argc] = strtok(NULL," \n");
  }
}

int sh1(){
  if(strcmp(cmd.argv[0], "cd") == 0){
    //printf("-------command is cd--------\n");
    int error = chdir(cmd.argv[1]);
    if(error < 0) 
      perror("cd");
    else {
        char *path = getcwd(NULL, 0);
        printf("%s\n", path);
        free(path);
    }
  }
  else if(strcmp(cmd.argv[0], "pwd") == 0) {
    //printf("-------command is pwd--------\n");
    char *path = getcwd(NULL, 0);
    printf("%s\n", path);
    free(path);
  }
  else if(strcmp(cmd.argv[0], "exit") == 0) {
    //printf("-------command is exit--------\n");
    exit(0);
  }
}

void mysys(char *command){
  cut_str(command);
  if(strcmp(cmd.argv[0], "cd") == 0 || strcmp(cmd.argv[0], "pwd") == 0 || strcmp(cmd.argv[0], "exit") == 0) {
    sh1();
    return;
  }
  else if(strcmp(cmd.argv[0], "echo") == 0){
    if(cmd.argv[cmd.argc-1][0] == '>'){
      //printf(">>>>>>>>>>>>>>>\n");
      int fd;
      int std_out;
      char *output_file;
      output_file = strtok(cmd.argv[cmd.argc-1],">");
      if(cmd.argv[cmd.argc-1][1] != '>'){
        fd = open(output_file, O_CREAT | O_RDWR | O_TRUNC, 0666);
      }
      else if(cmd.argv[cmd.argc-1][1] == '>'){
        fd = open(output_file, O_RDWR | O_APPEND, 0666);
      } 
      std_out = dup(1);
      dup2(fd,1);
      close(fd);
      cmd.argv[cmd.argc-1] = NULL;
      cmd.argc -= 1;
      pid_t pid_echo;
      pid_echo = fork();
      if(pid_echo == 0) {
        int error = execvp(cmd.argv[0], cmd.argv);
        if(error < 0) perror("execvp");
      }
      dup2(std_out,1);
      wait(NULL); 
      return;
    }
  }
  else if(strcmp(cmd.argv[0], "cat") == 0){
    if(cmd.argv[cmd.argc-1][0] == '<'){
      int fd;
      int std_in;
      char *input_file;
      input_file = strtok(cmd.argv[cmd.argc-1],"<");
      fd = open(input_file, O_RDONLY);
      std_in = dup(0);
      dup2(fd,0);
      close(fd);
      cmd.argv[cmd.argc-1] = NULL;
      cmd.argc -= 1;
      pid_t pid_cat;
      pid_cat = fork();
      if(pid_cat == 0) {
        int error = execvp(cmd.argv[0], cmd.argv);
        if(error < 0) perror("execvp");
      }
      dup2(std_in,0);
      wait(NULL); 
      return;
    }
    if(cmd.argv[cmd.argc-1][0] == '>'){
      int fd;
      int std_out;
      char *output_file;
      output_file = strtok(cmd.argv[cmd.argc-1],">");
      fd = open(output_file, O_CREAT | O_RDWR | O_TRUNC, 0666);
      std_out = dup(1);
      dup2(fd,1);
      close(fd);
      cmd.argv[cmd.argc-1] = NULL;
      cmd.argc -= 1;
    }
    if(cmd.argc == 1){
      char buf[512];
      int count;
      while(count = read(0,buf,512)){
          write(1,buf,count);
      }
    }
    //return;
  }
  pid_t pid;
  pid = fork();
  if(pid == 0) {
    int error = execvp(cmd.argv[0], cmd.argv);
    if(error < 0) perror("execvp");
  }
  wait(NULL);
}

int main() {
  char command[512];
  int count;
  while(1) {
    write(1, ">", sizeof(">"));
    count = read(0, command, sizeof(command));
    command[count] = '\0';
    mysys(command);
  }
  return 0;
}
